package cmd

import (
	"advertising/config/boot"
	"advertising/config/mysql"
	"advertising/internal/models"
	"advertising/internal/pkg"
	"fmt"
	"net/http"
	"path"
	"strconv"
	"strings"
	"time"

	"192.168.1.75/go-pkg/gormx"
	"192.168.1.75/go-pkg/helper"
	"github.com/samber/lo"
	"github.com/spf13/cobra"
	"gorm.io/datatypes"
	"gorm.io/gorm"
)

// MaRobot
type MaRobot struct {
	ID         string `gorm:"column:id;" json:"id"`
	MerchantID string `gorm:"column:merchant_id;" json:"merchant_id"`
	SalesID    string `gorm:"column:sales_id;" json:"sales_id"`
	RobotName  string `gorm:"column:robot_name;" json:"robot_name"`
}

// MaAd
type MaAd struct {
	ID          string         `gorm:"column:id;" json:"id"`
	Name        string         `gorm:"column:name;" json:"name"`
	SalesID     string         `gorm:"column:sales_id;" json:"sales_id"`
	LaunchScope string         `gorm:"column:launch_scope;" json:"launch_scope"`
	EndTime     datatypes.Date `gorm:"column:end_time;" json:"-"`
	Position    int            `gorm:"column:position;" json:"position"`
	FilePath    string         `gorm:"column:file_path;" json:"file_path"`
	CheckStatus int            `gorm:"column:check_status;" json:"check_status"`
	UseStatus   int            `gorm:"column:use_status;" json:"use_status"`
	Deleted     int            `gorm:"column:deleted;" json:"deleted"`
	StartTime   datatypes.Date `gorm:"column:start_time;" json:"-"`
	ModifyTime  int            `gorm:"column:modify_time;" json:"modify_time"`
	CheckMd5    string         `gorm:"column:check_md5;" json:"check_md5"`
	AddTime     int            `gorm:"column:add_time;" json:"add_time"`
	PlayTime    int            `gorm:"column:play_time;" json:"play_time"`
	Duration    int            `gorm:"column:duration;" json:"duration"`
}

// MaAdSourceDetail
type MaAdSourceDetail struct {
	ID       string `gorm:"column:id;" json:"id"`
	SourceID string `gorm:"column:source_id;" json:"source_id"`
	PathName string `gorm:"column:path_name;" json:"path_name"`
	Name     string `gorm:"column:name;" json:"name"`
	Deleted  int    `gorm:"column:deleted;" json:"deleted"`
	CheckMd5 string `gorm:"column:check_md5;" json:"check_md5"`
}

func init() {
	rootCmd.AddCommand(dataMigrateCmd)
}

var Online = true

var dataMigrateCmd = &cobra.Command{
	Use:   "data_migrate",
	Short: "data_migrate",
	Run: func(_ *cobra.Command, Args []string) {
		var db_old *gorm.DB
		var db_new *gorm.DB
		reqTime := time.Now()
		if Online {
			db_old, _ = gormx.New(gormx.Config{
				Host:     "rm-bp1q1c7c41l64k522.mysql.rds.aliyuncs.com",
				Port:     "3306",
				Username: "prod",
				Password: "Dadao1203123",
				Database: "sale-admin",
				Debug:    true,
			})
			db_new, _ = gormx.New(gormx.Config{
				Host:     "rm-bp1q1c7c41l64k522.mysql.rds.aliyuncs.com",
				Port:     "3306",
				Username: "prod",
				Password: "Dadao1203123",
				Database: "advertising",
				Debug:    true,
			})
		} else {
			boot.AppInit()
			db_old = mysql.NewDB()
			db_new = mysql.NewDB()
		}

		// 获取所有需要处理的广告信息
		var AdList []MaAd
		var count int64
		db_old.Table("ma_ad").
			Where("end_time > ? and use_status != 2 and deleted = 0", "2023-11-02").
			Find(&AdList).
			Count(&count)
		var DeviceIDList = []string{}
		var SourcePathList = []string{}
		var AdIDMap = make(map[string]MaAd)
		for _, v := range AdList {
			if !lo.Contains(DeviceIDList, v.SalesID) {
				DeviceIDList = append(DeviceIDList, v.SalesID)
			}
			if !lo.Contains(SourcePathList, v.FilePath) {
				SourcePathList = append(SourcePathList, v.FilePath)
			}
			AdIDMap[v.ID] = v
		}
		fmt.Println("广告总数:", count)

		// 获取所有设备
		var deviceList []MaRobot
		var deviceCount int64
		db_old.Table("ma_robot").
			Where("sales_id in ?", DeviceIDList).
			Select("sales_id,robot_name").
			Find(&deviceList).Count(&deviceCount)
		var deviceIDNameMap = make(map[string]string)
		for _, v := range deviceList {
			deviceIDNameMap[v.SalesID] = v.RobotName
		}
		fmt.Println("设备总数:", deviceCount)

		// 获取所有的素材
		var sourceList []MaAdSourceDetail
		var sourceCount int64
		db_old.Table("ma_ad_source_detail").
			Where("path_name in ?", SourcePathList).
			Select("path_name,name").
			Find(&sourceList).Count(&sourceCount)
		var sourcePathNameMap = make(map[string]string)
		for _, v := range sourceList {
			sourcePathNameMap[v.PathName] = v.Name
		}

		var groupInfo models.PublishDeviceGroup
		var groupCount int64
		db_new.Model(&models.PublishDeviceGroup{}).
			Where("name = ? and deleted_at = 0", "迁移专用投放组").
			Take(&groupInfo).
			Count(&groupCount)
		var groupID string
		if groupCount == 0 {
			// 生成投放组
			var groupData models.PublishDeviceGroup
			groupData.ID, _ = helper.UUID{}.String()
			groupData.Name = "迁移专用投放组"
			groupData.CreatedAt = time.Now().Unix()
			db_new.Model(&models.PublishDeviceGroup{}).Create(&groupData)
			groupID = groupData.ID
		} else {
			groupID = groupInfo.ID
		}
		var BatchInsertDevice []models.PublishDevice
		for _, v := range DeviceIDList {
			if _, ok := deviceIDNameMap[v]; ok {
				var deviceCount int64
				db_new.Model(&models.PublishDevice{}).
					Where("group_id = ? and robot_name = ?", groupID, deviceIDNameMap[v]).
					Count(&deviceCount)
				if deviceCount == 0 {
					var deviceData models.PublishDevice
					deviceData.ID, _ = helper.UUID{}.String()
					deviceData.GroupID = groupID
					deviceData.RobotName = deviceIDNameMap[v]
					deviceData.CreatedAt = time.Now().Unix()
					BatchInsertDevice = append(BatchInsertDevice, deviceData)
				}
			}
		}
		if len(BatchInsertDevice) > 0 {
			// 设备加入投放组
			db_new.Model(&models.PublishDevice{}).Create(&BatchInsertDevice)
		}

		var merchantCount int64
		db_new.Model(&models.MerchantPublishDeviceGroup{}).
			Where("merchant_id = 48 and group_id = ?", groupID).
			Count(&merchantCount)
		if merchantCount == 0 {
			// 商户绑定投放组
			var merchantData models.MerchantPublishDeviceGroup
			merchantData.ID, _ = helper.UUID{}.String()
			merchantData.MerchantID = "48"
			merchantData.GroupID = groupID
			db_new.Model(&models.MerchantPublishDeviceGroup{}).Create(&merchantData)
		}

		var BatchInsertPublishSchedule = []models.PublishSchedule{}
		var BatchInsertPublishScheduleAuditLog = []models.PublishScheduleAuditLog{}
		// 保存广告投放计划
		{
			// 先处理广告计划
			var ScheduleIDList = make(map[string]MaAd)
			var scheduleList = []models.PublishSchedule{}
			db_new.Model(&models.PublishSchedule{}).
				Where("merchant_id = 48 and deleted_at = 0").
				Find(&scheduleList)
			var scheduleMap = make(map[string]string)
			for _, v := range scheduleList {
				scheduleMap[v.Name] = v.ID
			}
			for adID, ad := range AdIDMap {
				var scheduleExist = false
				var scheduleInfoID string
				for name, id := range scheduleMap {
					if strings.Contains(name, "【迁移"+adID+"】") {
						scheduleExist = true
						scheduleInfoID = id
					}
				}
				if !scheduleExist {
					// 写入投放计划 publish_schedule
					var data models.PublishSchedule
					data.ID, _ = helper.UUID{}.String()
					data.Name = ad.Name + "【迁移" + adID + "】"
					data.Position = int8(ad.Position) + 1 // 1前 2后
					data.PublishType = 1
					data.DeviceCount = 1
					data.StartTime = time.Time(ad.StartTime).Unix()
					data.EndTime = time.Time(ad.EndTime).Unix() + 86399
					data.Status = 3
					data.MerchantID = "48"
					data.MerchantName = "大道运营"
					data.CreateUser = "48"
					data.CreateUserName = "大道运营"
					data.CreatedAt = time.Now().Unix()
					BatchInsertPublishSchedule = append(BatchInsertPublishSchedule, data)
					ScheduleIDList[data.ID] = ad

					// 投放计划审核 publish_schedule_audit_log
					var logData models.PublishScheduleAuditLog
					logData.ID, _ = helper.UUID{}.String()
					logData.MerchantID = "48"
					logData.ScheduleID = data.ID
					logData.MerchantName = "大道运营"
					logData.AuditMerchantID = "1"
					logData.AuditUser = "1"
					logData.AuditUsername = "admin"
					logData.AuditStatus = 1
					logData.AuditAt = time.Now().Unix()
					BatchInsertPublishScheduleAuditLog = append(BatchInsertPublishScheduleAuditLog, logData)
				} else {
					ScheduleIDList[scheduleInfoID] = ad
				}
			}
			var scheduleDeviceList = []models.PublishScheduleDevice{}
			db_new.Model(&models.PublishScheduleDevice{}).
				Where("merchant_id = 48").
				Where("deleted_at = 0").
				Find(&scheduleDeviceList)
			var scheduleDeviceMap = make(map[string]string)
			for _, v := range scheduleDeviceList {
				scheduleDeviceMap[v.ScheduleID+"+"+v.RobotName+"+"+strconv.Itoa(v.TerminalType)] = v.ID
			}
			var BatchInsertPublishScheduleDevice = []models.PublishScheduleDevice{}
			// 处理投放计划的关联设备
			for scheduleID, ad := range ScheduleIDList {
				if _, ok := deviceIDNameMap[ad.SalesID]; ok {
					if _, ok := scheduleDeviceMap[scheduleID+"+"+deviceIDNameMap[ad.SalesID]+"+"+strconv.Itoa(ad.Position+1)]; !ok {
						// 投放计划关联设备 publish_schedule_device
						var deviceData models.PublishScheduleDevice
						deviceData.ID, _ = helper.UUID{}.String()
						deviceData.MerchantID = "48"
						deviceData.ScheduleID = scheduleID
						deviceData.RobotName = deviceIDNameMap[ad.SalesID]
						deviceData.StartTime = time.Time(ad.StartTime).Unix()
						deviceData.EndTime = time.Time(ad.EndTime).Unix() + 86399
						deviceData.PublishType = 1 // 新增
						deviceData.TerminalType = ad.Position + 1
						deviceData.CreatedAt = time.Now().Unix()
						BatchInsertPublishScheduleDevice = append(BatchInsertPublishScheduleDevice, deviceData)
					}
				}
			}
			if len(BatchInsertPublishScheduleDevice) > 0 {
				db_new.Model(&models.PublishScheduleDevice{}).CreateInBatches(&BatchInsertPublishScheduleDevice, 10)
			}

			var scheduleMaterialList []models.PublishScheduleMaterial
			db_new.Model(&models.PublishScheduleMaterial{}).
				Where("merchant_id = 48 and deleted_at = 0").
				Find(&scheduleMaterialList)
			var scheduleMaterialMap = make(map[string]string)
			for _, v := range scheduleMaterialList {
				scheduleMaterialMap[v.ScheduleID] = v.MaterialID
			}

			var BatchInsertMaterial = []models.Material{}
			var BatchInsertMaterialAuditLog = []models.MaterialAuditLog{}
			var BatchInsertPublishScheduleMaterial = []models.PublishScheduleMaterial{}
			// 处理投放计划的关联素材
			// 先判断素材表是否存在
			var merchantList []models.Material
			db_new.Model(&models.Material{}).
				Where("merchant_id = 48 and deleted_at = 0").
				Find(&merchantList)
			var merchantMap = make(map[string]string)
			for _, v := range merchantList {
				merchantMap[v.Name+"+"+v.FilePath+"+"+strconv.Itoa(int(v.Position))] = v.ID
			}
			for scheduleID, ad := range ScheduleIDList {
				// 投放计划关联素材 publish_schedule_material
				if _, ok := sourcePathNameMap[ad.FilePath]; ok {
					var materialID string
					// 素材不存在时
					if exitMaterialID, ok := merchantMap[sourcePathNameMap[ad.FilePath]+"+"+ad.FilePath+"+"+strconv.Itoa(int(ad.Position+1))]; !ok {
						var fileType int8
						var fileSize int64
						var Size string
						// if Online {
						// 	fileInfo, err1 := os.Stat(ad.FilePath)
						// 	if err1 != nil {
						// 		fmt.Println("读取文件错误")
						// 		return
						// 	}
						// 	fileSize = fileInfo.Size()
						// 	size := pkg.Decimal(float64(fileSize)/(1024*1024), 2) //MB
						// 	Size = strconv.FormatFloat(size, 'f', -1, 64) + "MB"

						// 	if path.Ext(ad.FilePath) == ".mp4" { // video/mp4
						// 		fileType = 2 // 视频
						// 	} else { // image/png
						// 		fileType = 1 // 图片
						// 	}
						// } else {
						resp, err := http.Head("http://iybot.com" + ad.FilePath)
						if err != nil {
							fmt.Println("Error:", err)
							return
						}
						defer resp.Body.Close()

						if strings.Contains(resp.Header.Get("Content-Type"), "image") { // image/png
							fileType = 1
						} else { // video/mp4
							fileType = 2
						}
						fileSize = resp.ContentLength
						size := pkg.Decimal(float64(fileSize)/(1024*1024), 2) //MB
						Size = strconv.FormatFloat(size, 'f', -1, 64) + "MB"
						// }

						// 保存素材
						var materialData models.Material
						materialData.ID, _ = helper.UUID{}.String()
						materialData.Name = sourcePathNameMap[ad.FilePath]
						materialData.Type = fileType
						materialData.Position = int8(ad.Position) + 1
						materialData.Duration = 0
						materialData.Size = Size
						materialData.FileSize = fileSize
						materialData.Suffix = path.Ext(ad.FilePath)
						materialData.Status = 2
						materialData.FilePath = ad.FilePath
						materialData.MerchantID = "48"
						materialData.MerchantName = "大道运营"
						materialData.CreateUser = "48"
						materialData.CreateUserName = "大道运营"
						materialData.CreatedAt = time.Now().Unix()
						BatchInsertMaterial = append(BatchInsertMaterial, materialData)

						// 生成素材审核日志
						var logData models.MaterialAuditLog
						logData.ID, _ = helper.UUID{}.String()
						logData.MaterialID = materialData.ID
						logData.MerchantID = "48"
						logData.MerchantName = "大道运营"
						logData.AuditMerchantID = "1"
						logData.AuditUser = "1"
						logData.AuditUsername = "admin"
						logData.AuditStatus = 1
						logData.AuditAt = time.Now().Unix()
						BatchInsertMaterialAuditLog = append(BatchInsertMaterialAuditLog, logData)
						materialID = materialData.ID
						merchantMap[sourcePathNameMap[ad.FilePath]+"+"+ad.FilePath+"+"+strconv.Itoa(int(ad.Position+1))] = materialID
					} else {
						materialID = exitMaterialID
					}
					// 再看投放计划关联素材是否可用
					if _, ok := scheduleMaterialMap[scheduleID]; !ok {
						var scheduleMaterialData models.PublishScheduleMaterial
						scheduleMaterialData.ID, _ = helper.UUID{}.String()
						scheduleMaterialData.MerchantID = "48"
						scheduleMaterialData.ScheduleID = scheduleID
						scheduleMaterialData.MaterialID = materialID
						scheduleMaterialData.Duration = 30
						scheduleMaterialData.RepeatTimes = 1
						scheduleMaterialData.CreatedAt = time.Now().Unix()
						BatchInsertPublishScheduleMaterial = append(BatchInsertPublishScheduleMaterial, scheduleMaterialData)
					}
				}
			}
			if len(BatchInsertMaterial) > 0 {
				db_new.Model(&models.Material{}).CreateInBatches(&BatchInsertMaterial, 10)
			}
			if len(BatchInsertMaterialAuditLog) > 0 {
				db_new.Model(&models.MaterialAuditLog{}).CreateInBatches(&BatchInsertMaterialAuditLog, 10)
			}
			if len(BatchInsertPublishScheduleMaterial) > 0 {
				db_new.Model(&models.PublishScheduleMaterial{}).CreateInBatches(&BatchInsertPublishScheduleMaterial, 10)
			}

			if len(BatchInsertPublishSchedule) > 0 {
				db_new.Model(&models.PublishSchedule{}).CreateInBatches(&BatchInsertPublishSchedule, 10)
			}
			if len(BatchInsertPublishScheduleAuditLog) > 0 {
				db_new.Model(&models.PublishScheduleAuditLog{}).CreateInBatches(&BatchInsertPublishScheduleAuditLog, 10)
			}
		}

		RequestUsedTime := time.Since(reqTime)
		fmt.Println("used time:", RequestUsedTime.Milliseconds())
	},
}
